package com.oliver.proxy.midjourney.infrastructure.repository;

import com.oliver.proxy.midjourney.domain.aggregate.TaskAggregate;
import com.oliver.proxy.midjourney.domain.entity.InsertPoint;
import com.oliver.proxy.midjourney.domain.entity.TaskList;
import com.oliver.proxy.midjourney.domain.repository.TaskAggregateRepository;
import com.oliver.proxy.midjourney.infrastructure.mapper.TaskListMapper;
import com.oliver.proxy.midjourney.infrastructure.mapper.InsertPointMapper;
import org.springframework.stereotype.Repository;

import java.util.List;
import java.util.stream.Collectors;

@Repository
public class TaskAggregateRepositoryImpl implements TaskAggregateRepository {
    private final TaskListMapper taskListMapper;
    private final InsertPointMapper insertPointMapper;

    public TaskAggregateRepositoryImpl(TaskListMapper taskListMapper, InsertPointMapper insertPointMapper) {
        this.taskListMapper = taskListMapper;
        this.insertPointMapper = insertPointMapper;
    }

    @Override
    public Long saveAggregate(TaskAggregate taskAggregate) {
        taskListMapper.insert(taskAggregate.getTaskList());
        return taskAggregate.getTaskList().getTaskId();
    }

    @Override
    public void saveInsertPoints(List<InsertPoint> insertPoints) {
        insertPointMapper.batchInsert(insertPoints);
    }

    @Override
    public TaskAggregate findById(Long taskId) {
        TaskList taskList = taskListMapper.selectById(taskId);
        if (taskList == null) {
            return null;
        }

        TaskAggregate aggregate = new TaskAggregate(taskList);
        List<InsertPoint> insertPoints = insertPointMapper.selectByTaskId(taskId);
        insertPoints.forEach(aggregate::addInsertPoint);
        
        return aggregate;
    }

    @Override
    public List<TaskAggregate> findAll() {
        return taskListMapper.selectAll().stream()
                .map(this::createAggregateWithInsertPoints)
                .collect(Collectors.toList());
    }

    @Override
    public List<TaskAggregate> findByCategory(String category) {
        return taskListMapper.selectByCategory(category).stream()
                .map(this::createAggregateWithInsertPoints)
                .collect(Collectors.toList());
    }

    @Override
    public void update(TaskAggregate taskAggregate) {
        taskListMapper.update(taskAggregate.getTaskList());
    }

    @Override
    public void delete(Long taskId) {
        taskListMapper.deleteById(taskId);
    }

    private TaskAggregate createAggregateWithInsertPoints(TaskList taskList) {
        TaskAggregate aggregate = new TaskAggregate(taskList);
        List<InsertPoint> insertPoints = insertPointMapper.selectByTaskId(taskList.getTaskId());
        insertPoints.forEach(aggregate::addInsertPoint);
        return aggregate;
    }
}